<!DOCTYPE html>
<html>
<style type="text/css">
.row {
    width: 100%;
    height: 20px;
}

#ee {
    width: 200px;
    height: 400px;
}

.row div {
    display: inline-block;
    width: 10%;
    height: 100%;
}
</style>

<head>
    <title>demo</title>
</head>

<body>
    <div id="ee">
    </div>
    按键: 方向键左-向左移动 方向键右-向右移动 方向键下-向下移动 空格键-变换形状
</body>
<script type="text/javascript">
//TODO 产生错误的情况 
//fail 情况测试

// 转置的方法 -> 顺时针旋转90°
// var a = [2, 2, 2, 2, 2, 2];
// var result = [];
// if(!a[0].length){
//  for(var i=0;i<a.length;i++){
//      result[i] = [];
//      result[i].push(a[i])
//  }
// }else{
// for(var i=0;i<a[0].length;i++){
//  result.push([]);
//  for(var j=a.length;j>0;){
//      result[i].push(a[--j][i])
//  }
//  }
// }
// console.log(a)
// console.log(result)

var row = 20 ,col = 10;

var Store = new Array(row); //表格有20行

for (var i = 0; i < row; i++) {
    Store[i] = new Array(col); //每行有10列
}
var obj = document.getElementById('ee');

var colorSet = {
    0: '#000',
    1: '#03A9F4',
    2: '#44e04a',
    3: '#eceb0e',
    4: '#e61d2b',
    5: '#ff9800'
}
var shape = {
    square: [
        [1, 1],
        [1, 1]
    ],
    rectangle: [
        [2],
        [2],
        [2],
        [2],
    ],
    L: [
        [3, 0],
        [3, 0],
        [3, 3]
    ],
    Z: [
        [4, 0],
        [4, 4],
        [0, 4]
    ],

    tu: [
        [0, 5, 0],
        [5, 5, 5]
    ]
}
var originShape = {
    square: [
        [1, 1],
        [1, 1]
    ],
    rectangle: [
        [2],
        [2],
        [2],
        [2],
    ],
    L: [
        [3, 0],
        [3, 0],
        [3, 3]
    ],
    Z: [
        [4, 0],
        [4, 4],
        [0, 4]
    ],

    tu: [
        [0, 5, 0],
        [5, 5, 5]
    ]
}
var isRotate = 0; //当前的旋转

var shapeSet = ['square', 'rectangle', 'L', 'Z', 'tu']

var currentPosi = [0, 4];
var status = 'down';

var currentShape = getNewShape();

function getNewShape() {
    return shapeSet[(Math.random() * shapeSet.length) | 0];
}
var time = 500;

//初始化:
for (var i = 0; i < row; i++) {
        //i 行
        var div = document.createElement('div');
        div.className = 'row';
        obj.appendChild(div);
        for (var j = 0; j < col; j++) {
            //j 列
            var cdiv = document.createElement('div');
            var color = check(shape, i, j);
            cdiv.style.backgroundColor = colorSet[0]
            div.appendChild(cdiv);
        }
    }
var rowArray = obj.getElementsByClassName('row')

var render = function(shape) {
    for (var i = 0; i < row; i++) {
        for (var j = 0; j < col; j++) {
            //j 列
            var color = check(shape, i, j);
            var currentRow = rowArray[i].children;
            currentRow[j].style.backgroundColor = colorSet[color || 0]
            if (Store.length === currentPosi[0] + shape.length) {
                status = 'wait';
            }
        }
    }
}

function rotate(shape) {
    var result = [];
    if (!shape[0].length) {
        for (var i = 0; i < shape.length; i++) {
            result[i] = [];
            result[i].push(shape[i])
        }
    } else {
        for (var i = 0; i < shape[0].length; i++) {
            result.push([]);
            for (var j = shape.length; j > 0;) {
                result[i].push(shape[--j][i])
            }
        }
    }
    return result;
}


function addShape(shape) {
    console.log('run addShape')
    for (var o = 0; o < shape.length; o++) {
        for (var p = 0; p < shape[0].length; p++) {
            if (!Store[o + currentPosi[0]][p + currentPosi[1]]) {
                Store[o + currentPosi[0]][p + currentPosi[1]] = shape[o][p]
            }
        }
    }
    clear(checkIsRemove())
}

function checkIsRemove() {
    console.log('run checkIsRemove')
    var checkRow = Store.length;
    var clearArr = [];
    while (checkRow--) {
        var maxNum = 0;
        for (var u = 0; u < Store[checkRow].length; u++) {
            if (Store[checkRow][u]) {
                maxNum += 1;
            }
        }
        if (maxNum === 10) {
            clearArr.push(checkRow);
        }
    }

    return clearArr;
}

function clear(arr) {
    if (arr.length === 0) {
        return;
    }
    var clearNum = arr.length;
    while (clearNum--) {
        Store.splice(arr[clearNum], 1)
        Store.unshift([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
    }
}

function checkFail(shape) {
    var checkFailArr = Store[currentPosi[0] + shape.length - 1];
    for (var fi = 0; fi < shape[0].length; fi++) {
        if (checkFailArr[fi + currentPosi[1]]) {
            status = 'fail'
        }

    }

}

function check(shape, i, j) {
    if (i >= currentPosi[0] && j >= currentPosi[1] && i < currentPosi[0] + shape.length && j < currentPosi[1] + shape[0].length) {

        if (Store[i + 1] && Store[i + 1][j]) {
            if (shape[i - currentPosi[0]][j - currentPosi[1]]) {
                status = 'wait';
            }
        }
        if (currentPosi[0] === 0) {
            checkFail(shape);
        }

        return shape[i - currentPosi[0]][j - currentPosi[1]] || Store[i][j];
    } else {
        return Store[i][j];
    }
}

render(shape[currentShape]);


function run() {
    switch (status) {
        case 'down':
            currentPosi = [currentPosi[0] + 1, currentPosi[1]]
            break;
        case 'wait':
            addShape(shape[currentShape]);
            if (isRotate) {
                shape[currentShape] = originShape[currentShape];
                isRotate = 0;
            }
            currentPosi = [0, 4];
            status = 'down';
            //新选择一个
            currentShape = getNewShape();
            break;
        case 'fail':
            alert('fail')
            clearInterval(request);
            break;
    }
    render(shape[currentShape]);
}
var request = setInterval(run, time)

function checkLeft() {
    for (var cl = 0; cl < shape[currentShape].length; cl++) {
        if (Store[currentPosi[0] + cl][currentPosi[1] - 1]) {
            return false
        }
    }
    return true
}

function checkRight() {
    for (var cr = 0; cr < shape[currentShape].length; cr++) {
        if (Store[currentPosi[0] + cr][currentPosi[1] + shape[currentShape][0].length]) {
            return false;
        }
    }
    return true;

}
document.addEventListener('keydown', function(e) {
    if (e && e.keyCode === 37) {
        currentPosi[1] = (currentPosi[1] - 1) >= 0 && checkLeft() ? currentPosi[1] - 1 : currentPosi[1]
    }
    if (e && e.keyCode === 39) {
        currentPosi[1] = ((currentPosi[1] + 1 + shape[currentShape][0].length) <= Store[0].length) && checkRight() ? currentPosi[1] + 1 : currentPosi[1];
    }
    if (e && e.keyCode === 40) {
        if (time === 50) {
            return;
        }
        time = 50;
        clearInterval(request);
        request = setInterval(run, time)
    }
    if (e && e.keyCode === 32) {
        shape[currentShape] = rotate(shape[currentShape]);
        isRotate += 1;
    }
}, false)
document.addEventListener('keyup', function(e) {
    if (e && e.keyCode === 40) {
        time = 500;
        clearInterval(request);
        request = setInterval(run, time)
    }
}, false)
</script>

</html>